package org.jeecg.report.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.api.vo.Result;
import org.jeecg.report.dto.MaterialScrapDTO;
import org.jeecg.report.dto.OpScrapDTO;
import org.jeecg.report.mapper.MesCalculateScrapNumMapper;
import org.jeecg.report.service.IMesCalculateScrapNumService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 计算原料报废数量
 * @Author: LiCY
 * @Date:   2023-08-17
 * @Version: V1.0
 */
@Service
public class MesCalculateScrapNumServiceImpl  implements IMesCalculateScrapNumService {

    @Autowired
    private MesCalculateScrapNumMapper mesCalculateScrapNumMapper;
    @Autowired
    private CommonAPI commonAPI;

    @Override
    public ModelAndView exportXls(HttpServletRequest request, HttpServletResponse response, Map<String, Object> param) {
        //定义easyExcel导出的对象
        ExcelWriter excelWriter = null;
        WriteCellStyle exportExcelStyle = commonAPI.getExportExcelStyle();
        //头策略使用默认 设置字体大小
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 10);
        headWriteCellStyle.setWriteFont(headWriteFont);
        try {
            excelWriter = EasyExcel.write(response.getOutputStream()).build();
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename=demo.xlsx");
            ExcelWriterSheetBuilder materialScrap = EasyExcel.writerSheet(0, "原材料报废数量统计");
            ExcelWriterSheetBuilder opScrap = EasyExcel.writerSheet(1, "工序报废统计");
            materialScrap.head(MaterialScrapDTO.class)
                    .registerWriteHandler(new HorizontalCellStyleStrategy(headWriteCellStyle, exportExcelStyle));
            opScrap.head(OpScrapDTO.class)
                    .registerWriteHandler(new HorizontalCellStyleStrategy(headWriteCellStyle, exportExcelStyle));
            //查询数据并写入
            Result<List<MaterialScrapDTO>> calculateScrapNum = getCalculateScrapNum(param);
            param.put("isMaterial",1);
            param.put("isDebug",1);
            List<OpScrapDTO> opScrapNum2 = mesCalculateScrapNumMapper.getOpScrapNum(param);
            //根据参数查询对应工站异常录入报废数
            List<OpScrapDTO> opScrapNum4 = mesCalculateScrapNumMapper.getOpScrapNum4(param);
            param.put("isDebug",2);
            List<OpScrapDTO> debug1 = mesCalculateScrapNumMapper.getOpScrapNum(param);
            //根据参数查询对应工站异常录入报废数
            List<OpScrapDTO> debug2 = mesCalculateScrapNumMapper.getOpScrapNum4(param);
            if (!opScrapNum4.isEmpty()){
                opScrapNum2.addAll(opScrapNum4);
            }
            if (!debug1.isEmpty()){
                opScrapNum2.addAll(debug1);
            }
            if (!debug2.isEmpty()){
                opScrapNum2.addAll(debug2);
            }
            if(param.get("checked").equals("true")){
                List<OpScrapDTO> opScrapNum3 = mesCalculateScrapNumMapper.getOpScrapNum3(param);
                if (!opScrapNum3.isEmpty()){
                    opScrapNum2.addAll(opScrapNum3);
                }
            }
            opScrapNum2 = opScrapNum2.stream().sorted(Comparator.comparing(OpScrapDTO::getOp)).collect(Collectors.toList());
//            List<String> list = getChildrenCode(barCodeTraceDTO.getUnitsn());
            excelWriter.write(calculateScrapNum.getResult(), materialScrap.build());
            excelWriter.write(opScrapNum2, opScrap.build());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
        return null;
    }

    @Override
    public Result<List<MaterialScrapDTO>> getCalculateScrapNum(Map<String, Object> param) {
        param.put("isMaterial",0);
        param.put("isDebug",1);
        //根据参数查询对应工站报废数
        List<OpScrapDTO> list = mesCalculateScrapNumMapper.getOpScrapNum(param);
        //根据参数查询对应工站异常录入报废数
        List<OpScrapDTO> opScrapNum4 = mesCalculateScrapNumMapper.getOpScrapNum4(param);
        if (!opScrapNum4.isEmpty()){
            list.addAll(opScrapNum4);
        }
        param.put("isDebug",2);
        List<OpScrapDTO> opScrapNum5 = mesCalculateScrapNumMapper.getOpScrapNum4(param);
        List<OpScrapDTO> debugList = mesCalculateScrapNumMapper.getOpScrapNum(param);
        if (!debugList.isEmpty()){
            list.addAll(debugList);
        }
        if (!opScrapNum5.isEmpty()){
            list.addAll(opScrapNum5);
        }
        if(param.get("checked").equals("true")){
            List<OpScrapDTO> opScrapNum3 = mesCalculateScrapNumMapper.getOpScrapNum3(param);
            if (!opScrapNum3.isEmpty()){
                list.addAll(opScrapNum3);
            }
        }
        //根据产线 工单获取工序bom信息
        Map<String, Double> map = new HashMap<>();
        String opBom = mesCalculateScrapNumMapper.getOpBom(param);
        if (StringUtils.isNotBlank(opBom)){
            String[] split = opBom.split(";");
            for (String op : split) {
                String[] split1 = op.split(":");
                map.put(split1[0], Double.valueOf(split1[1]));
            }
        }
        //根据工站查询前边的所有数量
        List<MaterialScrapDTO> mesCalculateScrapNums = new ArrayList<>();
        List<String> ops =mesCalculateScrapNumMapper.getProductOp(param);
        list.forEach(item->{
            if (ops.contains(item.getOp())){
                MaterialScrapDTO opBomNum = mesCalculateScrapNumMapper.getProductOpNum(param, item.getOp());
                double num = opBomNum.getNum()*item.getNum();
                opBomNum.setNum(num);
                mesCalculateScrapNums.add(opBomNum);
            }else{
                List<MaterialScrapDTO> opBomNum = mesCalculateScrapNumMapper.getOpBomNum(param, item.getOp());
                opBomNum.forEach(item2->{
                    double num = 0.0;
                    if (map.containsKey(item2.getOp())){
                        Double s = map.get(item2.getOp());
                        num = item.getNum() * s;
                    }else{
                        num = item.getNum()*item2.getNum();
                    }
                    item2.setNum(num);
                    if (item.getIsDebug().equals("1")){
                        item2.setOpinions("调机报废");
                    }
                    mesCalculateScrapNums.add(item2);
                });
            }

        });
        //特殊逻辑 加入标签报废统计
        List<MaterialScrapDTO> labelScrapNums = mesCalculateScrapNumMapper.getLabelScrapNum(param);
        if (!labelScrapNums.isEmpty()){
            mesCalculateScrapNums.addAll(labelScrapNums);
        }

        //汇总
        Map<String, MaterialScrapDTO> map2 = new HashMap<String, MaterialScrapDTO>();
        for (MaterialScrapDTO s : mesCalculateScrapNums) {
            if (map2.containsKey(s.getPartItem()+s.getOpinions())){
                MaterialScrapDTO mesCalculateScrapNum = map2.get(s.getPartItem()+s.getOpinions());
                System.out.println(s.getDescription());
                mesCalculateScrapNum.setNum(mesCalculateScrapNum.getNum()+s.getNum());
            }else{
                map2.put(s.getPartItem()+s.getOpinions(),s);
            }
        }
        List<MaterialScrapDTO> collect = new ArrayList<>(map2.values());
        collect = collect.stream().sorted(Comparator.comparing(MaterialScrapDTO::getOpinions).thenComparing(MaterialScrapDTO::getOp)).collect(Collectors.toList());
        return  Result.OK(collect);
    }
}
